﻿using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Management.Infrastructure;
using OpenAiClient.Util.Models;

namespace OpenAiClient.Util.Hardware
{
    public static class ManagementInfrastructureHelper
    {
        /// <summary>
        /// 获取CPU信息列表
        /// </summary>
        /// <returns>CPU信息列表</returns>
        public static List<CpuInfo> GetCpuInfoList()
        {
            return GetInfoList<CpuInfo>("Win32_Processor");
        }

        /// <summary>
        /// 获取硬盘信息列表
        /// </summary>
        /// <returns>硬盘信息列表</returns>
        public static List<DiskInfo> GetDiskInfoList()
        {
            return GetInfoList<DiskInfo>("Win32_DiskDrive");
        }

        /// <summary>
        /// 获取主板信息列表
        /// </summary>
        /// <returns>主板信息列表</returns>
        public static List<BoardInfo> GetBoardInfoList()
        {
            return GetInfoList<BoardInfo>("Win32_BaseBoard");
        }

        private static List<T> GetInfoList<T>(string type) where T : class, new()
        {
            var infoList = new List<T>();
            var propertyList = typeof(T).GetProperties()
                .Where(t => t.MemberType == MemberTypes.Property && t.CanRead && t.CanWrite)
                .ToList();

            using (var cimSession = CimSession.Create(null))
            {
                var instances = cimSession.QueryInstances(@"root\CIMV2", "WQL", $@"SELECT * FROM {type}");
                foreach (var instance in instances)
                {
                    var info = new T();

                    foreach (var propertyValue in instance.CimInstanceProperties)
                    {
                        var propertyInfo = propertyList.FirstOrDefault(t => t.Name == propertyValue.Name);
                        if (propertyInfo == null)
                        {
                            continue;
                        }

                        if (propertyInfo.PropertyType == typeof(int)) //int
                        {
                            var value = int.TryParse(propertyValue.Value.ToString(), out var parseValue)
                                ? parseValue
                                : 0;
                            propertyInfo.SetValue(info, value);
                        }
                        else if (propertyInfo.PropertyType == typeof(long)) //long
                        {
                            var value = long.TryParse(propertyValue.Value.ToString(), out var parseValue)
                                ? parseValue
                                : 0;
                            propertyInfo.SetValue(info, value);
                        }
                        else //string
                        {
                            propertyInfo.SetValue(info, propertyValue.Value);
                        }
                    }

                    infoList.Add(info);
                }
            }

            return infoList;
        }
    }
}
